/**
 * @purpose 领域提供者基础实现。
 * @author daizs
 * @created Mar 4, 2010
 */
package platform.common.dao.impl;

import java.lang.reflect.Method;
import java.util.Map;

import org.apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import platform.common.bo.IdentifiableObj;
import platform.common.dao.IDomainProvider;
import platform.common.dao.IDomainProviderSet;
import platform.util.Util;


import platform.common.dao.impl.BaseDomainProviderImpl;
import platform.common.dao.impl.DaoConfigException;

public class BaseDomainProviderImpl extends DaoImpl implements IDomainProvider {
	/**
	 * 领域对象类。
	 */
	private Class<? extends IdentifiableObj> domainClass;
	/**
	 * 领域对象类名。
	 */
	private String domainClassName;

	/**
	 * log4j进行日志记录。
	 */
	private Logger log = Logger.getLogger(BaseDomainProviderImpl.class);
	/**
	 * 查询字符串
	 */
	private Map<String,Object> queryMap;

	/**
     * 领域对象提供者集合
     */
	protected IDomainProviderSet domainProviderSet;

	/**
     * @see platform.common.dao.IDomainProvider#getDomainClass()
     */
	@SuppressWarnings("unchecked")
	public Class<? extends IdentifiableObj> getDomainClass()throws DaoConfigException {
		if(domainClass==null){
			try {
				domainClass = (Class<? extends IdentifiableObj>)Class.forName(domainClassName);
			} catch (ClassNotFoundException e) {
				log.error("不能找到领域类"+domainClassName, e);
				throw new DaoConfigException(e);
			}
		}
		return domainClass;
	}

	/**
     * @see platform.common.dao.IDomainProvider#getHqlByQryName(String)
     */
	public String getHqlByQryName(String queryName) throws DaoConfigException {
		//利用Spring反射机制，依据属性名称获得Hql字符串
		BeanWrapper bw=new BeanWrapperImpl(this);
		queryName = queryName.substring(0,1).toLowerCase()+queryName.substring(1);
		String hql=(String) bw.getPropertyValue(queryName);
		return hql;
	}

	/**
     * @see platform.common.dao.IDomainProvider#getDynamicHqlByQryName(String)
     */
	public String getDynamicHqlByQryName(String queryName,Map<String,Object> dynamicMap) throws DaoConfigException {
		//利用反射机制，依据属性名称获得Hql字符串
		Class<?>[] parameterTypes=new Class[]{Map.class};
		String hql=null;
		try {
			Method m1 = this.getClass().getMethod(queryName,parameterTypes );
			hql = (String)m1.invoke(this, dynamicMap);
		} catch (Exception e) {
			throw new DaoConfigException(e);
		}
		return hql;
	}



	/**
     * @see platform.common.dao.IDomainProvider#getDomainClassName()
     */
	public String getDomainClassName() {
		return domainClassName;
	}

	/**
     * @see platform.common.dao.IDomainProvider#setDomainClassName(String)
     */
	public void setDomainClassName(String domainClassName) {
		this.domainClassName = domainClassName;
	}

	public Map<String,Object> getQueryMap() {
		return queryMap;
	}

	public void setQueryMap(Map<String,Object> queryMap) {
		this.queryMap = queryMap;
	}
	/**
     * @see platform.common.dao.IDomainProvider#newEmptyObj()
     */
	@SuppressWarnings("unchecked")
	public <T>T newEmptyObj()throws DaoConfigException{
		Class<? extends IdentifiableObj> cls=getDomainClass();
		T obj=null;
		if(cls!=null){
			try {
				obj=(T)cls.newInstance();
			} catch (Exception e) {
				throw new DaoConfigException("不能实例化名称为" + domainClassName
						+ "的领域对象");
			}
		}
		return obj;
	}
	/**
     * @see platform.common.dao.IDomainProvider#newEmptyObj()
     */
	public Object newQueryObj()throws DaoConfigException{
		Object bean=Util.createDynamicBean(queryMap);
		return bean;
	}

	public IDomainProviderSet getDomainProviderSet() {
		return domainProviderSet;
	}

	public void setDomainProviderSet(IDomainProviderSet domainProviderSet) {
		this.domainProviderSet = domainProviderSet;
	}


	/**
	 *
	 * <br/>方法描述:获得对象在数据库中的表名
	 *
	 * @param cls
	 *            对象的cls
	 * @return 对象在数据库中的表名
	 */
	protected String getDbTableName(Class<?> cls){
	    SessionFactory factory =getSessionFactory();
	    AbstractEntityPersister classMetadata =(SingleTableEntityPersister)factory.getClassMetadata(cls);
	    return classMetadata.getTableName();
	}

	/**
	 *
	 * <br/>方法描述:获得对象指定的属性在数据库中的字段名
	 *
	 * @param cls
	 *            对象的cls
	 * @param objAttributeName
	 *            对象的属性名
	 * @return 对象在数据库中的表名
	 */
	protected String getDbFieldName(Class<?> cls,String objAttributeName){
	    SessionFactory factory =getSessionFactory();
	    AbstractEntityPersister classMetadata =(SingleTableEntityPersister)factory.getClassMetadata(cls);

	    String[] colNames=classMetadata.getPropertyColumnNames(objAttributeName);
	    if(colNames.length>0){
	    	return colNames[0];
	    }
	    return null;
	}


}
